using System.Collections.Generic;
using Kopernikus.Parsing.GenericLexing;
using Kopernikus.Parsing.GenericParsing;
using Kopernikus.Parsing.Lexing;
using NUnit.Framework;

namespace Kopernikus.Parsing.Tests.GenericParsing
{
    [TestFixture]
    public class TestLexing
    {
        public void Test()
        {
            GenericParser<Parser, List<LexerMatch>> genericParser =
                GenericParser<Parser, List<LexerMatch>>.Create(new Parser());


            string input = @" a
        
b     c     d
  e
   

f
    g
";

            List<LexerMatch> matches = new List<LexerMatch>(genericParser.Parse(input));

            string[] expectedSymbols = new string[] {"a", "b", "c", "d", "e", "f", "g"};
            string[] expectedValues = new string[] {"a", "b", "c", "d", "e", "f", "g"};
            int[] expectedLines = new int[] {0, 2, 2, 2, 3, 6, 7};
            int[] expectedCols = new int[] {1, 0, 6, 12, 2, 0, 4};

            Queue<LexerMatch> queue = new Queue<LexerMatch>(matches);
            foreach (string s in expectedSymbols)
            {
                Assert.AreEqual(s, queue.Dequeue().Symbol.Name);
            }

            queue = new Queue<LexerMatch>(matches);
            foreach (string s in expectedValues)
            {
                Assert.AreEqual(s, queue.Dequeue().Value);
            }

            queue = new Queue<LexerMatch>(matches);
            foreach (int line in expectedLines)
            {
                Assert.AreEqual(line, queue.Dequeue().Line);
            }

            queue = new Queue<LexerMatch>(matches);
            foreach (int col in expectedCols)
            {
                Assert.AreEqual(col, queue.Dequeue().Col);
            }
        }

        [LexIgnore("\\s+")]
        private class Parser
        {
            [LexDefault(LexDefaultAttributeOptions.AnySingleCharacter)]
            public static List<LexerMatch> t_default(LexerMatch m)
            {
                List<LexerMatch> l = new List<LexerMatch>();
                l.Add(m);
                return l;
            }

            [CfgStart("P -> L")]
            public static List<LexerMatch> p_main(List<LexerMatch> l)
            {
                return l;
            }

            [Cfg("L -> E")]
            public static List<LexerMatch> p_list(List<LexerMatch> l)
            {
                return l;
            }

            [Cfg("L -> L E")]
            public static List<LexerMatch> p_list(IEnumerable<LexerMatch> l1, IEnumerable<LexerMatch> l2)
            {
                List<LexerMatch> l = new List<LexerMatch>();
                l.AddRange(l1);
                l.AddRange(l2);
                return l;
            }

            [Cfg("E -> a")]
            [Cfg("E -> b")]
            [Cfg("E -> c")]
            [Cfg("E -> d")]
            [Cfg("E -> e")]
            [Cfg("E -> f")]
            [Cfg("E -> g")]
            public static List<LexerMatch> p_sym(params List<LexerMatch>[] l)
            {
                return l[0];
            }
        }
    }
}